package com.bailan.foreat.service.impl;

import com.bailan.foreat.entity.*;
import com.bailan.foreat.es.ESProductRepository;
import com.bailan.foreat.mapper.CommentMapper;
import com.bailan.foreat.mapper.ItemMapper;
import com.bailan.foreat.mapper.OrderMapper;
import com.bailan.foreat.mapper.ProductMapper;
import com.bailan.foreat.service.*;
import com.bailan.foreat.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ste
 * @since 2023-02-21 07:50:43
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    RedisTemplate<String,Object> stringObjectRedisTemplate;
    @Autowired
    ESProductRepository esProductRepository;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    CartService cartService;

    @Autowired
    ItemMapper itemMapper;

    @Autowired
    ProductMapper productMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    StoreService storeService;

    @Autowired
    CommentService commentService;

    @Autowired
    ItemService itemService;

    @Autowired
    CommentMapper commentMapper;

    @Override
    public CartVo getCartVo(Integer userId, Integer[] productIds) {

        HashOperations<String, Object, Object> hashOperations = stringObjectRedisTemplate.opsForHash();
        List<Object> allCartItems = hashOperations.values(userId + "");

        CartVo cartVo = new CartVo();
        cartVo.setCartItemList(new ArrayList<>());

        //计算总价
        BigDecimal totalPrice = new BigDecimal("0.00");
        for(Object item : allCartItems){
            CartItem cartItem = (CartItem)item;
            for(Integer productId : productIds){
                //只有当前项的id在productIds中时才作为计算总价的一部分
                //同时拿到要结算的cartItem
                if (cartItem.getProductId().equals(productId)){
                    cartVo.getCartItemList().add(cartItem);
                    totalPrice = totalPrice.add(cartItem.getSumPrice());
                }
            }
        }

        cartVo.setTotalPrice(totalPrice);

        return cartVo;
    }

    @Override
    @Transactional
    public void createOrder(User currentUser, Integer[] productIds, Integer addressId) {

        //获取要结算项目的详情
        CartVo cartVo = getCartVo(currentUser.getId(), productIds);

        //创建一个订单出来
        //订单表Order中新增订单
        Order order = new Order();
        String orderNum = "WONIU"+new Date().getTime();
        order.setOrderNum(orderNum);
        order.setUserId(currentUser.getId());
        order.setAddressId(addressId);
        order.setStatus(0);  //order状态(0未⽀付)
        order.setTotalPrice(cartVo.getTotalPrice());
        order.setRefundReason("");
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());

        int num = orderMapper.insert(order);



        //存储订单详情
        List<CartItem> cartItems = cartVo.getCartItemList();

        for (CartItem cartItem : cartItems){
            Item item = new Item();
            item.setProductId(cartItem.getProductId());
            item.setProductName(cartItem.getProductName());
            item.setPrice(cartItem.getProductPrice());
            item.setBuyCount(cartItem.getBuyCount());
            item.setSumPrice(cartItem.getSumPrice());
            item.setUserId(currentUser.getId());
            item.setOrderId(order.getId());
            item.setStatus(0);//状态0未支付
            Product product = productMapper.selectById(cartItem.getProductId());
            item.setStoreId(product.getStoreId());

            itemMapper.insert(item);

            //更新商品的库存和购买量
            int updateNum = productMapper.updateProductStockCount(cartItem.getProductId(), cartItem.getBuyCount());
            if (updateNum<1){
                throw new RuntimeException("库存量不足，下单失败！");
            }
            productMapper.updateBuyCount(cartItem.getProductId(),cartItem.getBuyCount());

            //已经结算的商品要从购物车中清除掉
            cartService.updateBuyCount(currentUser.getId(),cartItem.getProductId(),0);

            //修改es库存和销量
            Optional<EsProduct> byId = esProductRepository.findById(Long.valueOf(cartItem.getProductId()));
            EsProduct esProduct = byId.get();
            esProductRepository.delete(esProduct);
            esProduct.setBuyCount(esProduct.getBuyCount()+cartItem.getBuyCount());
            esProduct.setStockCount(esProduct.getStockCount()-cartItem.getBuyCount());
            esProductRepository.save(esProduct);
        }

        //发送一个mq消息,15分钟后消费者需要检查该订单是否已支付,未支付订单需要被取消掉
        //消息生产者
        System.out.println("time1: "+new Date());
        rabbitTemplate.convertAndSend("cancelOrderNormalExchange","delayCancelOrder",order.getId());
        //发送消息的同时自定义消息的ttl
//        rabbitTemplate.convertAndSend("cancelOrderNormalExchange", "delayCancelOrder", order.getId(), new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
//                message.getMessageProperties().setExpiration("15000");  //配置消息的ttl
//                return message;
//            }
//        });

    }


    @Override
    @Transactional
    public String updateOrderStatus(Integer orderId, Integer newStatus) {
        // 由于自动取消,点击按钮需要校验order状态,防止后台已取消订单,而用户还未刷新页面
        // 1.校验状态
        Integer status = getOrderStatus(orderId);
        if(status==0){
            System.out.println("未支付,可以继续");
        } else if(status==1){
            System.out.println("订单已支付,请刷新页面!");
            return "订单已支付,请刷新页面！";
        } else if(status==2){
            System.out.println("订单已取消,请刷新页面!");
            return "系统已自动取消,请刷新页面！";
        } else {
            System.out.println("订单状态异常!");
            return "订单状态异常！请联系客服。";
        }
        // 2.更改当前订单所有item状态
        // orderItem状态(0未⽀付 1已支付,退单(按钮),签收(按钮) 2已取消 3退款中 4已退款 5已签收,评论(按钮) 6已评论)[3按钮,7状态]
        List<Item> itemList = itemService.selectByOrderId(orderId);
        if(newStatus == 1){
            //支付订单,所有item改为状态:1已支付
            for (Item item : itemList) {
                updateItemStatus(item.getId(),1);
            }
        } else if(newStatus == 2){
            //取消订单,所有item改为状态:6已取消
            for (Item item : itemList) {
                // 返还库存量,购买量
                int updateNum = productMapper.updateProductStockCount(item.getProductId(), item.getBuyCount()*(-1));
                productMapper.updateBuyCount(item.getProductId(),item.getBuyCount()*(-1));
                updateItemStatus(item.getId(),2);

                //修改es库存和销量
                Optional<EsProduct> byId = esProductRepository.findById(Long.valueOf(item.getProductId()));
                EsProduct esProduct = byId.get();
                esProductRepository.delete(esProduct);
                esProduct.setBuyCount(esProduct.getBuyCount()-item.getBuyCount());
                esProduct.setStockCount(esProduct.getStockCount()+item.getBuyCount());
                esProductRepository.save(esProduct);
            }
        }
        // 3.更改order状态
        // order状态(0未⽀付,取消(按钮) 1已支付 2已取消(手动,自动)
        orderMapper.updateOrderStatus(orderId,newStatus);
        return "ok";
    }

    @Override
    public void updateItemStatus(Integer itemId, Integer newStatus) {
        // orderItem状态(0未⽀付 1已支付,退单(按钮),签收(按钮) 2已取消 3退款中 4已退款 5已签收,评论(按钮) 6已评论)[3按钮,7状态]
        orderMapper.updateItemStatus(itemId,newStatus);
    }

    @Override
    public Integer getOrderStatus(Integer orderId){
        return orderMapper.selectById(orderId).getStatus();
    }

    @Override
    public void updateOrderItemStatus(Integer orderId, Integer storeId, Integer newStatus) {
        // 修改orderItem下所有item的状态
        // orderItem状态(0未⽀付 1已支付,退单(按钮),签收(按钮) 2已取消 3退款中 4已退款 5已签收,评论(按钮) 6已评论)[3按钮,7状态]

        //更改当前订单所有item状态
        List<ItemVo> itemVoList = itemMapper.selectItemListOfOrderItem(orderId,storeId);
        for (ItemVo itemVo : itemVoList) {
            itemService.updateItemStatus(itemVo.getId(),newStatus);
        }
    }
    @Override
    public void receivingOrderItem(Integer orderId, Integer storeId, Integer newStatus){
        //签收orderItem,修改状态
        //改状态: 1(已支付)->5(已签收)
        updateOrderItemStatus(orderId,storeId,newStatus);
        //签收后,一定时间未评价,自动评价
        System.out.println("time-c1: "+new Date());
        OrderItem orderItem = new OrderItem();
        orderItem.setStoreId(storeId);
        List<ItemVo>itemVoList= itemMapper.selectItemListOfOrderItem(orderId,storeId);
        Integer itemId = itemVoList.get(0).getId();
        rabbitTemplate.convertAndSend("autoEvaluationNormalExchange","autoEvaluation",itemId);
    }
    @Override
    public void refundOrderItem(Integer orderId, Integer storeId, Integer newStatus, String refundReason){
        //退单orderItem
        List<ItemVo> itemVoList = itemMapper.selectItemListOfOrderItem(orderId,storeId);
        for (ItemVo itemVo : itemVoList) {
            //改状态: 1(已支付)->2(退单中)
            orderMapper.updateRefund(itemVo.getId(),newStatus,refundReason);
        }
    }

    @Override
    public String checkOrderItem(Integer itemId){
        ItemVo itemVo = itemMapper.selectItemVo(itemId);
        Integer status =  itemVo.getStatus();
        // orderItem状态(0未⽀付 1已支付,退单(按钮),签收(按钮) 2已取消 3退款中 4已退款 5已签收,评论(按钮) 6已评论)[3按钮,7状态]
        if(status == 5){
            return "ok";
        }else if(status==6){
            System.out.println("系统已自动评价,请刷新页面!");
            return "系统已自动评价,请刷新页面！";
        }else{
            System.out.println("其他状态,请刷新页面!");
            return "状态异常，请刷新页面！";
        }
    }
    @Override
    @Transactional
    public String reviewOrderItem(List<Comment> comments, Integer userId){
        synchronized(userId+"") {
            // 1.校验状态
            String result = checkOrderItem(comments.get(0).getItemId());
            if(!"ok".equals(result)){
                return result;
            }
            System.out.println("item状态为未评价,可以继续");

            // 2.
            Date createTime = new java.sql.Date(new Date().getTime());
            for (Comment comment : comments) {
                //添加Comment
                if (comment.getGrade() == 0) {
                    comment.setGrade(5);
                    System.out.println("grade为0,默认5星好评");
                }
                comment.setUserId(userId);
                comment.setCreateTime(createTime);
                if ("".equals(comment.getContent())) {
                    comment.setContent("该用户未填写内容。");
                }
                commentService.add(comment);
                // 修改item状态
                // orderItem状态(0未⽀付 1已支付,退单(按钮),签收(按钮) 2已取消 3退款中 4已退款 5已签收,评论(按钮) 6已评论)[3按钮,7状态]
                itemService.updateItemStatus(comment.getItemId(), 6);
            }
        }
        return "ok";
    }

    @Override
    public Page<OrderVo> queryAllOrder(Integer currentPage, Integer pageSize, String keyword, User currentUser) {
//┗ ┏ ┫ ━
//                 ┏━ order信息
//        orderVo ━┫                              ┏━ store商铺信息
//                 ┗━ orderItemList ━━ orderItem ━┫
//                                                ┗━ itemVoList订单项集合 ━━ itemVo: item + storeId
//
//        order --> 根据user_id获取分页数据orderPageResult --> 遍历集合将order信息放入orderVo --> 根据order_id获取item集合 --> 联表item转itemVo(拿store_id) --> 根据item获取所有store集合,去重 --> 将商铺信息和itemVoList放入orderItem里(根据storeId获取对应的item集合) 将orderItemList放入orderVo --> 将orderPageResult的分页信息和orderVoList转到pageVo里
//
//      1.获得对应分页数据 2.获取对象里的集合属性 3.放回分页数据
//

        Page<Order> page = new Page<>(currentPage,pageSize);
        //1.查询登录用户所有订单并分页
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",currentUser.getId());
        queryWrapper.orderByDesc("create_time");
        Page<Order> orderPageResult = orderMapper.selectPage(page,queryWrapper);

        //2.order转orderVo(获取每个订单具体项的集合)
        List<OrderVo> orderVoList = new ArrayList<>();
        for(Order order : orderPageResult.getRecords()){
            //2.1.order转orderVo
            OrderVo orderVo = new OrderVo();
            orderVo.setId(order.getId());
            orderVo.setOrderNum(order.getOrderNum());
            orderVo.setOrderTime(order.getCreateTime());
            orderVo.setTotalPrice(order.getTotalPrice());
            orderVo.setStatus(order.getStatus());

            //2.2.获取orderItem
            List<OrderItem> orderItemList = new ArrayList<>();
            {
                List<Item> itemList = itemService.selectByOrderId(order.getId());
                List<ItemVo> itemVoList = new ArrayList<>();
                //2.2.1.item转itemVo (为了获取每个购物项的storeId和productImg)
                for (Item item : itemList) {
                    ItemVo itemVo = itemMapper.selectItemVo(item.getId());
                    itemVoList.add(itemVo);
                }
                //2.2.2.获取所有商铺集合
                List<Store> storeList = itemVoList.stream().map(itemVo -> {
                    //根据itemVo获取store
                    return storeService.getById(itemVo.getStoreId());
                }).collect(Collectors.toList());
                //商铺集合去重
                storeList = storeList.stream().distinct().collect(Collectors.toList());

                //2.2.3.将商铺信息和itemVoList放入orderItem里
                Integer i = 0;
                for (Store s : storeList) {
                    OrderItem orderItem = new OrderItem();
                    //1.商铺信息
                    orderItem.setStoreId(s.getId());
                    orderItem.setStoreName(s.getStoreName());
                    orderItem.setStoreImg(s.getStoreImg());
                    //2.根据storeId获取对应的item集合
                    List<ItemVo> itvList = new ArrayList<>();
                    for (ItemVo itemVo : itemVoList) {

                        if (itemVo.getStoreId().equals(s.getId())) {
                            itvList.add(0,itemVo);
                        }
                    }
                    orderItem.setItemVoList(itvList);
                    //设置商铺的状态(从第一个item获取)
                    //item和orderItem状态一致
                    orderItem.setStatus(itvList.get(0).getStatus());

                    orderItemList.add(0,orderItem);
                }
            }
            orderVo.setOrderItemList(orderItemList);

            //2.3.订单集合
            orderVoList.add(orderVo);
        }

        //3.orderPageResult的分页信息转到pageVo里
        Page<OrderVo> pageVo = new Page<>(currentPage,pageSize);
        pageVo.setRecords(orderVoList);
        System.out.println("orderVoList:"+orderVoList);
        pageVo.setTotal(orderPageResult.getTotal());
        System.out.println("orderPageResult.getTotal():"+orderPageResult.getTotal());
        pageVo.setSize(orderPageResult.getSize());
        System.out.println("orderPageResult.getSize():"+orderPageResult.getSize());
        pageVo.setCurrent(orderPageResult.getCurrent());
        System.out.println("orderPageResult.getCurrent():"+orderPageResult.getCurrent());


        return pageVo;
    }

    //打印ArrayList
    public String printArrayList(List list){
        String listStr = "[";
        for (Object o : list) {
            if(o instanceof List){
                printArrayList((List)o);
            }else {
                listStr += o.toString();
            }
        }
        listStr+="]";
        return listStr;
    }

}
